/*
 * UART_PC.c
 *
 * Created: 2012-7-13 22:25:56
 *  Author: Administrator
 */ 


#include "BLDC.h"




unsigned char tx_buffer[TX_BUFFER_SIZE];
volatile unsigned char tx_wr_index,tx_rd_index,tx_counter;
volatile unsigned char rx_buffer[RX_BUFFER_SIZE];
unsigned char rx_command[RX_FRAME_SIZE];
volatile unsigned char rx_counter = 0;
volatile unsigned char rx_input = 0;
volatile unsigned char rx_output = 0;
volatile unsigned char Uart_RX_Completion_Flag = 0;//Completion flag
unsigned char usart_rx_timeout;

static int uart_putchar(char c, FILE *stream);

FILE uartio = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); 

void Init_USART(void)
{
    UCSR0B=(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);//(1<<TXEN0);//
    UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
    UBRR0L=(SYSTEM_FREQUENCY/USART_BAUD/16-1)%256;
    UBRR0H=(SYSTEM_FREQUENCY/USART_BAUD/16-1)/256;
    DDRD &= ~(1<<PORTD0);
    DDRD |= (1<<PORTD1);
    stdout = &uartio;
}

void my_print(unsigned char *pbuff)
{
    unsigned char i;
    for(i=0;;i++)
    {
        if(pbuff[i] == 0)
        {
            return;
        }
        while((UCSR0A & DATA_REGISTER_EMPTY)==0);
        UDR0=pbuff[i];
    }
}

void my_print_hex(unsigned int num)
{
    unsigned char i;
    unsigned char temp_char;
    while((UCSR0A & DATA_REGISTER_EMPTY)==0);
    UDR0='0';
    while((UCSR0A & DATA_REGISTER_EMPTY)==0);
    UDR0='x';
    for(i=0;i<4;i++)
    {
        temp_char = (num>>(12-4*i))&0x0f;
        if(temp_char)
        {
            for(;i<4;i++)
            {
                temp_char = (num>>(12-4*i))&0x0f;
                while((UCSR0A & DATA_REGISTER_EMPTY)==0);
                if(temp_char < 0x0a)
                    UDR0=temp_char+'0';
                else
                    UDR0=temp_char+'A';
            }
            return;
        }
    }
}

void my_print_dec(unsigned int num)
{
    unsigned char i;
    unsigned char temp_buff[5];

    if(num == 0)
    {
        while((UCSR0A & DATA_REGISTER_EMPTY)==0);
        UDR0='0';
        return;
    }
    temp_buff[0] = num/10000;
    temp_buff[1] = (num%10000)/1000;
    temp_buff[2] = (num%1000)/100;
    temp_buff[3] = (num%100)/10;
    temp_buff[4] = num%10;
    for(i=0;i<5;i++)
    {
        if(temp_buff[i])
        {
            for(;i<5;i++)
            {
                while((UCSR0A & DATA_REGISTER_EMPTY)==0);
                UDR0=temp_buff[i] + '0';
            }
            return;
        }
    }
}


void my_print_tab(void)
{
    while((UCSR0A & DATA_REGISTER_EMPTY)==0);
    UDR0=0x0D;
    while((UCSR0A & DATA_REGISTER_EMPTY)==0);
    UDR0=0x0A;
}

static int uart_putchar(char c, FILE *stream)
{ 
    if (c == '\n') 
        uart_putchar('\r', stream); 
        
    loop_until_bit_is_set(UCSR0A, UDRE0); 
    UDR0 = c; 
    
    return 0; 
}

unsigned char calculate_checksum(uint8_t *pdata,uint8_t len)
{
    uint8_t i;
    uint8_t sum=0;
    for(i=0;i<len;i++)
    {
        sum ^= pdata[i];
    }
    return sum;
}

unsigned char usart_scan(void)
{
    unsigned char temp_scan_input;
    unsigned char temp_scan_output;
    unsigned char i,temp_sum;
    static unsigned char temp_scan_index;
    
    temp_scan_input = rx_input;
    temp_scan_output = rx_output;

    if(usart_rx_timeout)
        usart_rx_timeout--;
    else
        temp_scan_index = 0;
        
    while(temp_scan_input != temp_scan_output)
    {
        switch(temp_scan_index)
        {
            case 0:
                if(rx_buffer[temp_scan_output] == RX_FRAME_HEAD)
                {
                    rx_command[temp_scan_index] = rx_buffer[temp_scan_output];
                    temp_scan_index++;
                }
                break;
            case 1:
                if((rx_buffer[temp_scan_output])
                    &&(rx_buffer[temp_scan_output] <= (RX_FRAME_SIZE-3)))
                {
                    rx_command[temp_scan_index] = rx_buffer[temp_scan_output];
                    temp_scan_index++;
                }
                break;
            default:
                rx_command[temp_scan_index] = rx_buffer[temp_scan_output];
                temp_scan_index++;
                if(temp_scan_index == (rx_command[1]+3))
                {
                    temp_sum = calculate_checksum(&rx_command[1],(temp_scan_index-2));
                //    if(temp_sum == rx_command[temp_scan_index-1])
                    {
                        return TRUE;
                    }
                }
                
                break;
        }
        temp_scan_output = (temp_scan_output+1)%RX_BUFFER_SIZE;
    }
    rx_output = temp_scan_output;
    
    return FALSE;
}

ISR (USART_RX_vect)
{
    unsigned char data;
    unsigned char temp_input;
    unsigned char temp_output;

    data=UDR0;
    sei();
    usart_rx_timeout = 2;//10ms
    temp_input = rx_input;
    temp_output = rx_output;
    temp_input = (temp_input+1)%RX_BUFFER_SIZE;
    if(temp_input != temp_output)
    {
        rx_buffer[rx_input]=data;
        rx_input = temp_input;
    }
    cli();
}
